﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using MLOCore.Utility;
using System.ComponentModel;
using System.IO;

namespace MLOCore
{
    public class Library : INotifyPropertyChanged
    {
        public string Name { get; set; }
        public string ParentDirectory { get; set; }

        private SongFileCollection files;


        public void Analyze()
        {
          LoadFromDirectory(ParentDirectory);
        }

        /// <summary>
        /// Gets the files.
        /// </summary>
        /// <value>The files.</value>
        public SongFileCollection Files
        {
            get
            {
                files = files ?? new SongFileCollection();
                return files;
            }
        }

        /// <summary>
        /// Loads from directory.
        /// </summary>
        /// <param name="dir">The dir.</param>
        public void LoadFromDirectory(string dir)
        {
            if (!(System.IO.Directory.Exists(dir))) return;

            SongFile sf;

            foreach (string file in System.IO.Directory.GetFiles(dir))
            {
                sf = new SongFile(this, file);

                if (ID3Reader.CanProcess(file))
                {
                    ID3Information info = ID3Reader.Process(file);

                    if (!string.IsNullOrEmpty(info.album))
                        sf.Nodes.Add(new NameValueNode(ID3FileInfo.Album, info.album));
                    if (!string.IsNullOrEmpty(info.artist))
                        sf.Nodes.Add(new NameValueNode(ID3FileInfo.Artist, info.artist));
                    if (!string.IsNullOrEmpty(info.comment))
                        sf.Nodes.Add(new NameValueNode(ID3FileInfo.Description, info.comment));
                    if (!string.IsNullOrEmpty(info.genre))
                        sf.Nodes.Add(new NameValueNode(ID3FileInfo.Genre, info.genre));
                    if (!string.IsNullOrEmpty(info.title))
                        sf.Nodes.Add(new NameValueNode(ID3FileInfo.Title, info.title));
                    if (info.year > 0)
                        sf.Nodes.Add(new NameValueNode(ID3FileInfo.Track, info.track.ToString()));
                    if (info.track > 0)
                        sf.Nodes.Add(new NameValueNode(ID3FileInfo.Year, info.year.ToString()));

                    Files.Add(sf);
                }
            }

            foreach (string item in System.IO.Directory.GetDirectories(dir))
            {
                LoadFromDirectory(item);
            }

            OnPropertyChanged("Files");
        }

        #region Save
        /// <summary>
        /// Saves the specified file.
        /// </summary>
        /// <param name="file">The file.</param>
        public void Save(string file)
        {
            if (string.IsNullOrEmpty(file)) return;

            BinaryFormatter bf = new BinaryFormatter();

            System.IO.FileStream fs = new System.IO.FileStream(file, System.IO.FileMode.Create);

            try
            {
                bf.Serialize(fs, this);
            }
            finally
            {
                fs.Close();
                fs.Dispose();
            }
        }

        /// <summary>
        /// Loads from file.
        /// </summary>
        /// <param name="file">The file.</param>
        /// <returns></returns>
        public static Library LoadFromFile(string file)
        {
            if (string.IsNullOrEmpty(file)) return null;

            BinaryFormatter bf = new BinaryFormatter();

            System.IO.FileStream fs = new System.IO.FileStream(file, System.IO.FileMode.Open);

            Library result;

            try
            {
                result = (Library)bf.Deserialize(fs);
            }
            finally
            {
                fs.Close();
                fs.Dispose();
            }

            return result;
        }
        #endregion


        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Triggers the PropertyChanged event.
        /// </summary>
        public virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion
      
    }
}
